#ifndef _X_MYSQL_H
#define _X_MYSQL_H
#include <iostream>
#include <unordered_map>
#include <vector>
#include <string>
#include <mysql/mysql.h>
#include "x_sqlbuilder.h"
#include "../inih/cpp/INIReader.h"
namespace x_3rd
{
    class x_mysql_base{
        public:
            x_mysql_base(){}
            x_mysql_base(const char* ip,const char* name,\
            const char* passw,uint32_t port,
            const char* db_name,const char* charset):db_server_ip(ip),\
            db_user_name(name),db_user_passw(passw),db_server_port(port)\
            ,db_name(db_name),db_charset(charset){}
        public:
            void load_mysql_config(std::unordered_map<std::string,std::string>& conf)
            {
                db_server_ip = conf["db_server_ip"];
                db_server_port = std::atoi(conf["db_server_port"].c_str());
                db_name = conf["db_name"];
                db_user_name = conf["db_user_name"];
                db_user_passw = conf["db_user_passw"];
                db_charset = conf["db_charset"];
            }
            void load_mysql_config(INIReader& reader)
            {
                db_server_ip=reader.GetString("database","db_server_ip","127.0.0.1");
                db_server_port= std::atoi(reader.GetString("database","db_server_port","3306").c_str());
                db_name=reader.GetString("database","db_name","UNKNOWN");
                db_user_name=reader.GetString("database","db_user_name","UNKNOWN");
                db_user_passw=reader.GetString("database","db_user_passw","UNKNOWN");
                db_charset=reader.GetString("database","db_charset","utf8");
            }
        public:
            uint32_t    db_server_port;
            std::string db_server_ip;
            std::string db_name;
            std::string db_user_name;
            std::string db_user_passw;
            std::string db_charset;

    };

    class x_mysql : public x_mysql_base{
        public:
            x_mysql(){}
            x_mysql(const char* ip,const char* name,\
            const char* passw,uint32_t port,\
            const char* db_name,const char* charset):\
            x_mysql_base{ip,name,passw,port,db_name,charset},mysql(NULL){}
            ~x_mysql();
        public:
            bool init();
            bool init(const char* ip,const char* name,const char* passw,uint32_t port,\
            const char* db_name,const char* charset);
            bool connect();
            void disconnect();
        private:
            bool execute(const char* sSql);
        public:
            size_t          execute_raw_sql(const std::string& sql);
            size_t          execute_raw_sql(const char* format ...);
            size_t          sql_insert(const std::string& table_name,const DataRecord& record);
            size_t          sql_delete(const std::string& table_name,const DataRecord& record,Conditions& condis);
            DataResult      sql_query(const std::string& table_name,const std::vector<std::string> &fields,\
                            const DataRecord& record,Conditions& condis);
            DataResult      sql_query(const std::string& sql);
            DataResult      sql_query(const char* format ...);
            size_t          sql_update(const std::string& table_name,const DataRecord& record,const DataRecord& wheres,Conditions& condis);
            bool            sql_existRecord(const std::string& table_name,const std::vector<std::string> &fields,\
                            const DataRecord& record,const Conditions& condis);
            uint64_t        last_insertID();
            uint64_t        getAffectedRows();
            void            show_dataResult(DataResult& result);
            std::string     getLastSql() {return last_sql;}
            std::string     escapeString(std::string& sFrom);
        private:
            Field::FIELD_DATA_TYPE praseFieldType(enum_field_types type);
        private:
            MYSQL* mysql = NULL;
            bool   isinit = false;
            bool   isconnected = false;
            std::string last_sql;
    };
}

#endif